package com.mulong.mall.service.impl;

import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.mulong.common.dao.mall.InventoryDao;
import com.mulong.common.domain.pojo.mall.SupplierChannel;
import com.mulong.common.domain.pojo.mall.custom.InventoryQuery;
import com.mulong.common.exception.ErrorEnums;
import com.mulong.common.exception.MulongException;
import com.mulong.mall.constants.Constants;
import com.mulong.mall.domain.bo.supplier.Inventory;
import com.mulong.mall.domain.param.supplier.GetInventoryByPageParam;
import com.mulong.mall.domain.result.supplier.GetInventoryByPageResult;
import com.mulong.mall.domain.result.supplier.UploadInventoryResult;
import com.mulong.mall.service.SupplierService;
import com.mulong.mall.service.support.SupplierServiceSupport;
import com.mulong.mall.util.MallRequestContext;

import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * SupplierServiceImpl
 * 
 * @author mulong
 * @data 2021-06-21 13:45:07
 */
@Slf4j
@Service
public class SupplierServiceImpl implements SupplierService {
    @Autowired
    private InventoryDao inventoryDao;
    @Autowired
    private SupplierServiceSupport supplierServiceSupport;

    /**
     * 查询库存
     * 
     * @author mulong
     */
    @Override
    public GetInventoryByPageResult getInventoryByPage(GetInventoryByPageParam param) {
        SupplierChannel supplierChannel = supplierServiceSupport.getSupplierChannel();
        if (supplierChannel == null) {
            log.error("supplierChannel is null");
            throw new MulongException(ErrorEnums.ILLEGAL_REQUEST);
        }
        InventoryQuery query = new InventoryQuery();
        query.setSku(param.getSku());
        query.setSupplierChannelId(supplierChannel.getId());
        query.setOrderBy("`create_time` DESC, `sku` ASC");
        int pageNo = param.getPageNo() == null ? Constants.DEFAULT_PAGE_NO : param.getPageNo();
        int pageSize = param.getPageSize() == null ? Constants.DEFAULT_PAGE_SIZE : param.getPageSize();
        PageHelper.startPage(pageNo, pageSize, true);
        Page<com.mulong.common.domain.pojo.mall.Inventory> page = (Page<com.mulong.common.domain.pojo.mall.Inventory>) inventoryDao.query(query);
        GetInventoryByPageResult getInventoryByPageResult = new GetInventoryByPageResult(page.getPageNum(), page.getPageSize(), (int)page.getTotal());
        List<com.mulong.common.domain.pojo.mall.Inventory> list = page.getResult();
        if (!CollectionUtils.isEmpty(list)) {
            getInventoryByPageResult.setResult(list.stream().map(Inventory::new).collect(Collectors.toList()));
        }
        return getInventoryByPageResult;
    }

    /**
     * 添加库存
     * 
     * @author mulong 
     */
    @Override
    public Inventory addInventory(Inventory inventory) {
        SupplierChannel supplierChannel = supplierServiceSupport.getSupplierChannel();
        if (supplierChannel == null) {
            log.error("supplierChannel is null");
            throw new MulongException(ErrorEnums.ILLEGAL_REQUEST);
        }
        inventory.setId(null);
        inventory.setCreateTime(null);
        com.mulong.common.domain.pojo.mall.Inventory newRecord = inventory.buildInventory();
        newRecord.setSupplierChannelId(supplierChannel.getId());
        supplierServiceSupport.richInventory(newRecord);
        newRecord = inventoryDao.add(newRecord, MallRequestContext.getUsername());
        return new Inventory(newRecord);
    }

    /**
     * 查询库存
     * 
     * @author mulong 
     */
    @Override
    public Inventory getInventoryById(Long id) {
        SupplierChannel supplierChannel = supplierServiceSupport.getSupplierChannel();
        if (supplierChannel == null) {
            log.error("supplierChannel is null");
            throw new MulongException(ErrorEnums.ILLEGAL_REQUEST);
        }
        com.mulong.common.domain.pojo.mall.Inventory record = inventoryDao.queryById(id);
        if (record == null) {
            throw new MulongException(ErrorEnums.RESOURCE_NOT_EXISTS);
        }
        if (!supplierChannel.getId().equals(record.getSupplierChannelId())) {
            throw new MulongException(ErrorEnums.RESOURCE_NOT_EXISTS);
        }
        return new Inventory(record);
    }

    /**
     * 更新库存
     * 
     * @author mulong 
     */
    @Override
    public Inventory putInventoryById(Long id, Inventory inventory) {
        SupplierChannel supplierChannel = supplierServiceSupport.getSupplierChannel();
        if (supplierChannel == null) {
            log.error("supplierChannel is null");
            throw new MulongException(ErrorEnums.ILLEGAL_REQUEST);
        }
        if (!id.equals(inventory.getId())) {
            log.error("id mismatch");
            throw new MulongException(ErrorEnums.ILLEGAL_PARAM);
        }
        inventory.setCreateTime(null);
        com.mulong.common.domain.pojo.mall.Inventory record = inventoryDao.queryById(id);
        if (record == null) {
            throw new MulongException(ErrorEnums.RESOURCE_NOT_EXISTS);
        }
        if (!supplierChannel.getId().equals(record.getSupplierChannelId())) {
            throw new MulongException(ErrorEnums.RESOURCE_NOT_EXISTS);
        }
        com.mulong.common.domain.pojo.mall.Inventory newRecord = inventory.buildInventory();
        record.setSku(newRecord.getSku());
        record.setOriginalSize(newRecord.getOriginalSize());
        record.setNormalizedSize(null);
        record.setQty(newRecord.getQty());
        record.setMarketPrice(newRecord.getMarketPrice());
        record.setDiscount(newRecord.getDiscount());
        supplierServiceSupport.richInventory(record);
        inventoryDao.put(record, MallRequestContext.getUsername());
        return new Inventory(record);
    }

    /**
     * 删除库存
     * 
     * @author mulong 
     */
    @Override
    public Inventory deleteInventoryById(Long id) {
        SupplierChannel supplierChannel = supplierServiceSupport.getSupplierChannel();
        if (supplierChannel == null) {
            log.error("supplierChannel is null");
            throw new MulongException(ErrorEnums.ILLEGAL_REQUEST);
        }
        com.mulong.common.domain.pojo.mall.Inventory record = inventoryDao.queryById(id);
        if (record == null) {
            throw new MulongException(ErrorEnums.RESOURCE_NOT_EXISTS);
        }
        if (!supplierChannel.getId().equals(record.getSupplierChannelId())) {
            throw new MulongException(ErrorEnums.RESOURCE_NOT_EXISTS);
        }
        inventoryDao.delete(record, MallRequestContext.getUsername());
        return new Inventory(record);
    }

    /**
     * 上传库存
     * 
     * @author mulong
     */
    @Override
    public UploadInventoryResult uploadInventory(MultipartFile file) {
        SupplierChannel supplierChannel = supplierServiceSupport.getSupplierChannel();
        if (supplierChannel == null) {
            log.error("supplierChannel is null");
            throw new MulongException(ErrorEnums.ILLEGAL_REQUEST);
        }
        if (file.isEmpty()) {
            log.error("upload file is empty");
            throw new MulongException(ErrorEnums.UPLOAD_FILE_EMPTY);
        }
        try (InputStream inputStream = file.getInputStream()) {
            ExcelReader reader = ExcelUtil.getReader(inputStream, Constants.SUPPLIER_UPLOAD_INVENTORY_SHEET_NAME);
            List<com.mulong.common.domain.pojo.mall.Inventory> inventoryRecords = supplierServiceSupport.buildInventoryList(reader, supplierChannel);
            reader.close();
            if (!CollectionUtils.isEmpty(inventoryRecords)) {
                try {
                    inventoryDao.addAll(supplierChannel.getId(), inventoryRecords, 1000, MallRequestContext.getUsername());
                } catch (Exception e) {
                    log.error(e.getMessage(), e);
                    throw new MulongException(ErrorEnums.HANDLE_FAILED_TEMPLETE.format(e.getMessage()));
                }
            }
            UploadInventoryResult uploadInventoryResult = new UploadInventoryResult();
            uploadInventoryResult.setInventoryCount(inventoryRecords.size());
            return uploadInventoryResult;
        } catch (MulongException e) {
            throw e;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new MulongException(ErrorEnums.UPLOAD_FILE_SERVER_ERROR);
        }
    }

}
